
/**
 * @file	fdwatch.c
 * @brief
 * @author
 * @date
 * @note
 * @see
 * @version $Id$
**/

#include <strings.h>
#include <stdio.h>

#include "fdwatch.h"
#include "logout.h"

#define DEF_FDMAX	512


////////////////////////////////////////

#define SELECT

////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
// select

#ifdef SELECT

#include <sys/select.h>

int fd_rdlist[DEF_FDMAX];
int fd_rdcnt;
int fd_rdidx;
int fd_wtlist[DEF_FDMAX];
int fd_wtcnt;
int fd_wtidx;

fd_set fd_rdset;
fd_set fd_wtset;
int fd_max;
struct timeval fd_to;

static int fd_fillset();

////////////////////////////////////////

// 初始化变量,设置超时时间.
int fd_init(int invertal)
{
	int i;

	fd_rdcnt=0;
	fd_wtidx=0;
	fd_wtcnt=0;
	for(i=0;i<DEF_FDMAX;i++) {
		fd_rdlist[i]=-1;
		fd_wtlist[i]=-1;
	}

	fd_to.tv_sec = invertal/1000;
	fd_to.tv_usec = invertal%1000*1000;

	return 0;
}

// 添加连接.
int fd_add(int fd, int type)
{
	int i;

	switch(type) {
		case DEF_RFD:
			// 是否已经有了.
			for(i=0;i<fd_rdcnt;i++) {
				if(fd_rdlist[i] == fd) {
					return i;
				}
			}
			// 是否达到最多了.
			if(fd_rdcnt > DEF_FDMAX) {
				break;
			}
			// 添加.
			fd_rdlist[fd_rdcnt]=fd;
			fd_rdcnt++;
			break;
		case DEF_WFD:
			// 是否已经有了.
			for(i=0;i<fd_wtcnt;i++) {
				if(fd_wtlist[i] == fd) {
					return i;
				}
			}
			// 是否已经达到最多了.
			if(fd_wtcnt > DEF_FDMAX) {
				break;
			}
			// 添加.
			fd_wtlist[fd_wtcnt]=fd;
			fd_wtcnt++;
			break;
		default:
			break;
	}

	return 0;
}

// 删除连接.
int fd_del(int fd)
{
	int i = 0;

	for(i=0;i<fd_rdcnt;i++) {
		if(fd_rdlist[i] == fd) {
			fd_rdlist[i] = fd_rdlist[fd_rdcnt-1];
			fd_rdlist[fd_rdcnt-1] = -1;
			fd_rdcnt--;
			break;
		}
	}

	return 0;
}

// 填充连接符集.
static int fd_fillset()
{
	int i;

	FD_ZERO(&fd_rdset);
	FD_ZERO(&fd_wtset);
	fd_max = 0;

	for(i=0;i<fd_rdcnt;i++) {
		FD_SET(fd_rdlist[i], &fd_rdset);

		if(fd_rdlist[i] > fd_max) {
			fd_max = fd_rdlist[i];
		}
	}

	// 有效写描述符统计.
	fd_wtcnt = 0;
	for(i=0;i<DEF_FDMAX;i++) {
		if(fd_wtlist[i]!= -1) {
			fd_wtlist[fd_wtcnt] = fd_wtlist[i];
			fd_wtcnt++;
		}
	}

	for(i=0;i<fd_wtcnt;i++) {
		FD_SET(fd_wtlist[i], &fd_wtset);
	}

	return 0;
}

// 等待连接.
int fd_watch()
{
	int num=0;
	struct timeval tv;

	fd_wtidx = 0;		// 重要.
	fd_rdidx = 0;

	tv.tv_sec=fd_to.tv_sec;
	tv.tv_usec=fd_to.tv_usec;
	fd_fillset();

	num = select(fd_max+1, &fd_rdset, &fd_wtset, NULL, &tv);

	return num;
}

// 得到有效连接.
int fd_get(int type)
{
	int i=0;
	int fd = -1;

	switch(type) {
		case DEF_RFD:
			for(i=fd_rdidx;i<fd_rdcnt;i++) {
				if(FD_ISSET(fd_rdlist[i], &fd_rdset)) {
					fd_rdidx = i+1;
					fd = fd_rdlist[i];
					break;
				}
			}
			break;
		case DEF_WFD:
			for(i=fd_wtidx;i<fd_wtcnt;i++) {
				if(FD_ISSET(fd_wtlist[i], &fd_wtset)) {
					fd_wtidx = i+1;
					fd = fd_wtlist[i];
					fd_wtlist[i]=-1;
					break;
				}
			}
			break;
		default:
			break;
	}

	return fd;
}

#endif // SELECT

////////////////////////////////////////
// poll

#ifdef POLL

#include <poll.h>

static struct pollfd fds[DEF_FDMAX];
int timeout = 0;
int fd_cnt;
int	fd_wtidx;
int	fd_rdidx;

// 初始化,设置超时时间.
int fd_init(int invertal)
{
	int i;

	fd_cnt=0;
	fd_rdidx=0;
	fd_wtidx=0;
	for(i=0;i<DEF_FDMAX;i++) {
		fds[i].fd=-1;
	}
	timeout=invertal;

	return 0;
}

// 添加连接.
int fd_add(int fd, int type)
{
	int i;
	int idx = -1;

	// 是否已经存在.
	for(i=0;i<fd_cnt;i++) {
		if(fds[i].fd == fd) {
			idx=i;
			break;
		}
	}

	// 是否已经达到最大.
	if(idx == -1 && fd_cnt >= DEF_FDMAX) {
		return -1;
	}

	// 确定位置.
	if(idx == -1) {
		idx = fd_cnt;
		fd_cnt++;
	}

	// 设置描述符.
	fds[idx].fd = fd;
	fds[idx].events = 0;
	fds[idx].revents = 0;

	// 设置事件.
	switch(type) {
		case DEF_RFD:
			fds[idx].events |= POLLIN;
			break;
		case DEF_WFD:
			fds[idx].events |= POLLOUT;
			break;
		default:
			break;
	}

	return 0;
}

// 删除连接.
int fd_del(int fd)
{
	int i;

	// 只管删除.不管类型.
	for(i=0;i<DEF_FDMAX;i++) {
		if(fds[i].fd == fd) {
			fds[i].fd = fds[fd_cnt].fd;
			fds[i].events = fds[fd_cnt].events;
			fds[i].revents = fds[fd_cnt].revents;
			fds[fd_cnt].fd=-1;
			fds[fd_cnt].events = 0;
			fds[fd_cnt].revents = 0;

			fd_cnt--;

			break;
		}
	}

	return 0;
}

int fd_watch()
{
	int num=0;

	fd_wtidx = 0;		// 重要.
	fd_rdidx = 0;

	num = poll(fds, fd_cnt, timeout);

	return num;
}

int fd_get(int type)
{
	int i=0;
	int fd = 0;

	switch(type) {
		case DEF_RFD:
			for(i=fd_rdidx;i<fd_cnt;i++) {
				if(fds[i].revents & POLLIN) {
					fd_rdidx = i+1;
					fd = fds[i].fd;
					break;
				}
			}
			break;
		case DEF_WFD:
			for(i=fd_wtidx;i<fd_cnt;i++) {
				if(fds[i].revents & POLLOUT) {
					fd_wtidx = i+1;
					fd = fds[i].fd;
					// 设置可写标记,只检测一次.
					fds[i].events &= (~POLLOUT);
					break;
				}
			}
			break;
		default:
			break;
	}

	return fd;
}

#endif // POLL

////////////////////////////////////////
// KQUEUE

#ifdef KQUEUE

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>

int kq;
static struct kevent fds[DEF_FDMAX];
static struct kevent rfds[DEF_FDMAX];
struct timespec ts;
int fd_cnt;
int	fd_wtidx;
int	fd_rdidx;
int evnum;

// 初始化,设置超时时间.
int fd_init(int invertal)
{
	int i;

	fd_cnt=0;
	fd_rdidx=0;
	fd_wtidx=0;
	for(i=0;i<DEF_FDMAX;i++) {
		fds[i].ident=-1;
	}
	ts.tv_sec=invertal/1000;
	ts.tv_nsec=invertal%1000*1000*1000;

	kq = kqueue();

	return 0;
}

// 添加连接.
int fd_add(int fd, int type)
{
	int i;

	// 是否已经达到最大.
	if(fd_cnt >= DEF_FDMAX) {
		return -1;
	}

	// 设置事件.
	switch(type) {
		case DEF_RFD:
			EV_SET(&fds[fd_cnt], fd, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0);
			break;
		case DEF_WFD:
			EV_SET(&fds[fd_cnt], fd, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, 0);
			break;
		default:
			break;
	}

	fd_cnt++;

	i = kevent(kq, fds, fd_cnt, NULL, 0, NULL);
	if(i == -1) {
		perror("kevent() error:");
	}

	return 0;
}

// 删除连接.
int fd_del(int fd)
{
	int i;
	int ridx = -1;
	int widx = -1;

	// 是否已经存在.
	for(i=0;i<fd_cnt;i++) {
		if(fds[i].ident == fd && fds[i].filter|EVFILT_READ) {
			EV_SET(&fds[i], fd, EVFILT_READ, EV_DELETE|EV_ENABLE, 0, 0, 0);
			ridx=i;
		}
		if(fds[i].ident == fd && fds[i].filter|EVFILT_WRITE) {
			EV_SET(&fds[i], fd, EVFILT_WRITE, EV_DELETE|EV_ENABLE, 0, 0, 0);
			widx=i;
		}
	}

	// 是否找到.
	if(ridx == -1 && widx == -1) {
		return -1;
	}

	i = kevent(kq, fds, fd_cnt, NULL, 0, NULL);
	if(i == -1) {
		perror("kevent() error:");
	}

	if(ridx != -1) {
		fds[ridx].ident = fds[fd_cnt].ident;
		fds[ridx].filter = fds[fd_cnt].filter;
		fds[ridx].flags = fds[fd_cnt].flags;
		bzero(&fds[fd_cnt], sizeof(fds[fd_cnt]));
		fds[fd_cnt].ident=-1;
		fd_cnt--;
	}
	if(widx != -1 && widx != ridx) {
		fds[widx].ident = fds[fd_cnt].ident;
		fds[widx].filter = fds[fd_cnt].filter;
		fds[widx].flags = fds[fd_cnt].flags;
		bzero(&fds[fd_cnt], sizeof(fds[fd_cnt]));
		fds[fd_cnt].ident=-1;
		fd_cnt--;
	}

	return 0;
}

int fd_watch()
{
	evnum = 0;
	fd_wtidx = 0;		// 重要.
	fd_rdidx = 0;

	bzero(rfds, sizeof(rfds));

	evnum = kevent(kq, NULL, 0, rfds, DEF_FDMAX, &ts);
	if(evnum == -1) {
		perror("kevent() error:");
	}

	return evnum;
}

int fd_get(int type)
{
	int i=0;
	int fd = 0;

	switch(type) {
		case DEF_RFD:
			for(i=fd_rdidx;i<evnum;i++) {
				if(rfds[i].filter & EVFILT_READ) {
					fd_rdidx = i+1;
					fd = rfds[i].ident;
					break;
				}
			}
			break;
		case DEF_WFD:
			for(i=fd_wtidx;i<evnum;i++) {
				if(rfds[i].filter & EVFILT_WRITE) {
					int retval;

					fd_wtidx = i+1;
					fd = rfds[i].ident;

					// 设置可写标记,只检测一次.
					EV_SET(&rfds[i], fds[i].ident, EVFILT_WRITE, EV_DELETE|EV_ENABLE, 0, 0, 0);
					retval = kevent(kq, fds, fd_cnt, NULL, 0, NULL);
					if(retval == -1) {
						perror("kevent() error:");
					}
					break;
				}
			}
			break;
		default:
			break;
	}

	return fd;
}

#endif // KQUEUE

////////////////////////////////////////


